/**
 *
 * 显示明细项的表格组件
 *
 * */
import React, {ReactNode} from "react";
import {ICellInputProps} from "@/biz-components/claim-items/components-v2/cell-input";
import {getAllTypesOfMetasByPageCode} from "@/biz-components/claim-items/components";
import {Button, Checkbox, Table} from "antd";
import {CommonTableCell} from "@/biz-components/claim-items/components-v2/CommonTableCell";
import { formatMessage } from '@/utils/i18n-transform';
import ClaimItemsDataUtil from "@/biz-components/claim-items/ClaimItemsDataUtil";

/**
 * 表格里面某一个元模型属性对应的那一列的配置
 * */
export interface ICommonTableAttributeColumnOption<T, E extends {[name: string]: any}> {
	// 元模型里面的属性名称
	name: string;
	/*
	 * 输入组件以及组件的额外（除了ICellInputProps以外的）props
	 * args[0] 是组件
	 * args[1] 是组件的额外参数， 可以是对象，页可以是function。如果是function argv[0] 是这一行的数据
	 * */
	component?: [React.ComponentType<ICellInputProps<T> & E>, E];
	/*
	校验规则，如果元模型页面配置了必填，会按照string 或者 number 必填的校验规则来校验。如果这里配置了校验规则，使用
	这里的校验规则
	*/
	validator?: (v: T, record: any) => boolean;

	/*
	* 隐藏逻辑
	* */
	hide?: boolean;

	/*
	 * 禁用逻辑
	 * record 是这一行的数据
	 * */
	disabled?: boolean | ((record: any) => boolean);

	/*
	 * 有一些列值变化之后需要设置对应的名称列（比如选择了员工编码，设置员工姓名）
	 * 配置名称列的属性名称，可以自动处理这个逻辑 (输入组件的onChange的第二个参数是名称列的值, onChange(code, name))
	 * */
	relationForNameAttribute?: string;

	/**
	 * 当某一行的数据变化之后的处理
	 * */
	onRowChange?: (row: any) => void;
	/**
	 * 渲染详情
	 * */
	renderDetail?: (value: any, record: any) => any;

}

export interface ICommonTableProps {
	// 元模型编码
	pageCode: string;
	// 元模型meta
	metaArr?: any[];

	value: any[];
	onChange: (value: any[]) => void;
	detailMode: boolean;
	/*
	* form ily 对认领项组件的校验是否有错误信息
	* */
	claimItemsInvalid: boolean;

	/*
	* 向父级组件传递一个校验表格数据的方法
	* */
	validateFunctionRef: React.MutableRefObject<(() => boolean) | null>,

	/*
	 * 是否可以添加数据
	 * */
	addOperation?: boolean;
	onAdd?: () => void;

	/*
	* 是否有删除操作
	* */
	deleteOperation?: boolean;
	onDelete?: (record: any) => void;
	deleteDisabled?: (record: any) => boolean;

	/*
	 * 是否有复选框操作
	 * */
	checkOperation?: boolean;
	// record null  check all uncheck all
	onCheckChange?: (record: object | null, checked: boolean) => void;

	/**
	 * 渲染操作列
	 * */
	renderOptions?: (record: any) => ReactNode;

	/*
	 * 表格列的配置
	 * 如果某一列没有给配置，就直接渲染value
	 * */
	columnsOptionArr: ICommonTableAttributeColumnOption<any, any>[]
}

export class CommonTable extends React.Component<ICommonTableProps> {
	state: {
		metaArr: any[]
	} = {
		metaArr: []
	};
	constructor(props: ICommonTableProps) {
		super(props);
		this.validate = this.validate.bind(this);
		this.addCellValidator = this.addCellValidator.bind(this);
		this.removeCellValidator = this.removeCellValidator.bind(this);
	}

	componentDidMount() {
		this.props.validateFunctionRef && (this.props.validateFunctionRef.current = this.validate);
		this.initMeta();
	}
	componentDidUpdate(prevProps: Readonly<ICommonTableProps>, prevState: Readonly<{}>, snapshot?: any) {
		if(
			(prevProps.metaArr !== this.props.metaArr)
			||
			(prevProps.pageCode !== this.props.pageCode)
		) {
			this.initMeta();
		}
	}

	componentWillUnmount() {
		this.props.validateFunctionRef && (this.props.validateFunctionRef.current = null);
	}

	/**
	 * 表格里面每一个单元格的校验方法
	 * */
	cellValidatorArr: Array<() => boolean> = [];
	/**
	 * 单元格onMount 的时候将自己的校验方法添加到cellValidatorArr里面
	 * */
	addCellValidator (func: () => boolean) {
		this.cellValidatorArr.push(func);
	};
	/**
	 * 单元格unMount 的时候将自己的校验方法从cellValidatorArr里面移除
	 * */
	removeCellValidator (func: () => boolean) {
		this.cellValidatorArr = this.cellValidatorArr.filter((item) => item !== func);
	};

	/**
	 * 校验这个表格的数据
	 * 调用每一个单元格的校验方法
	 * */
	validate(): boolean {
		return this.cellValidatorArr.every((func) => func());
	}

	/**
	 * 查询元模型配置信息
	 * */
	initMeta() {
		const {pageCode, metaArr} = this.props;
		if(metaArr) {
			this.setState({metaArr: metaArr});
		} else {
			getAllTypesOfMetasByPageCode(pageCode)
				.then((data) => {
					this.setState({metaArr: data.tableColumnMetas});
				})
		}
	}

	getColumnOperationByName(name: string): ICommonTableAttributeColumnOption<any, any> | null {
		return this.props.columnsOptionArr.find((item) => item.name === name) || null;
	}

	render() {
		const {value, onChange,
			//claimItemsInvalid,
			detailMode,
			addOperation,
			onAdd = () => null,
			checkOperation,
			onCheckChange = () => null,
			deleteOperation,
			onDelete = () => null,
			deleteDisabled,
			renderOptions
		} = this.props;
		const {metaArr} = this.state;

		return (
			<div>
				{
					!detailMode && addOperation &&
					<Button type={"primary"} onClick={onAdd}>{formatMessage({id: 'common.add'})}</Button>
				}
				{/*<div style={{width: '100%', overflow: 'auto', maxHeight: '300px', scrollbarColor: '#999'}}>*/}
					<Table
						scroll={{x: 'max-content', y: 350}}
						dataSource={value || []}
						pagination={false}
						rowKey={ClaimItemsDataUtil.tempIdAttributeName}
						size={'small'}

					>
						{
							!detailMode && checkOperation &&
							<Table.Column
								fixed
								title={<Checkbox onChange={(e) => onCheckChange(null, e.target.checked)}/>}
								render={(t, r: any) => {
									return(
										<span style={{minWidth: '80px', display: 'inline-block'}}>
										<Checkbox
											checked={!!r.__checked}
											onChange={(e) => {
												onCheckChange(r, e.target.checked)
											}}
										/>
										</span>
									)
								}}
							/>
						}
						{
							!detailMode && deleteOperation &&
							<Table.Column fixed title={formatMessage({ id: 'config.common.label.operation' })} render={(t,r:any) => {
								return (
									<div style={{minWidth: '80px', display: 'inline-block'}}>
										<Button
											disabled={typeof deleteDisabled === 'function' ? deleteDisabled(r) : false}
											size={"small"} onClick={() => onDelete(r)}>{formatMessage({id: 'others.delete'})}</Button>
									</div>
								)
							}} />
						}
						{
							!detailMode && renderOptions &&
							<Table.Column  fixed title={formatMessage({ id: 'config.common.label.operation' })} render={(t,r:any) => {
								return (
									<div style={{minWidth: '80px', display: 'inline-block'}}>
										{renderOptions(r)}
									</div>

								)
							}} />
						}

						{
							metaArr.map((meta) => {
								const name = meta.key;
								let hide = false;
								const columnOption = this.getColumnOperationByName(name);
								if(columnOption) {
									if(typeof columnOption.hide === 'boolean') {
										hide = columnOption.hide;
									}
								}
								if(hide) {
									return null;
								}
								if(meta.props.hidden === '1') {
									return null;
								}
								return (
									<Table.Column
										key={meta.key}
										title={meta.label}
										dataIndex={name}
										render={(t, r) => {
											return (
												<div style={{minWidth: '120px', display: 'inline-block'}}>
													<CommonTableCell
														name={name}
														recordData={r}
														onChange={() => {
															onChange([...value]);
														}}
														shouldShowValidateMessage={true}
														addValidator={this.addCellValidator}
														removeValidator={this.removeCellValidator}
														meta={meta}
														detailMode={detailMode}
														columnOption={columnOption}
													/>
												</div>
											)
										}}
									/>
								)
							})
						}
					</Table>
				{/*</div>*/}

			</div>
		)
	}
}


